#pragma once
#include <Engine/IMaterial.h>
#include <Engine/Math/Vec4.h>
#include <Engine/Foundation/VectorMap.h>
#include <Engine/Renderer/Shaders/Constants.h>
#include <Engine/Renderer/RendererStructs.h>

namespace fastbird
{
	class IShader;
	class ITexture;
	class Material : public IMaterial
	{
	public:
		static IMaterial* Find(const char* filepath);

		Material();
		virtual ~Material();

		//--------------------------------------------------------------------
		// IMaterial Interfaces
		//--------------------------------------------------------------------
		virtual bool LoadFromFile(const char* filepath);
		virtual const char* GetName() const { return mName.c_str(); }

		virtual void SetAmbientColor(float r, float g, float b, float a);
		virtual void SetAmbientColor(const Vec4& ambient);
		virtual void SetDiffuseColor(float r, float g, float b, float a);
		virtual void SetDiffuseColor(const Vec4& diffuse);
		virtual void SetSpecularColor(float r, float g, float b, float shine);
		virtual void SetSpecularColor(const Vec4& specular);
		virtual void SetEmissiveColor(float r, float g, float b, float strength);
		virtual void SetEmissiveColor(const Vec4& emissive);

		virtual void SetTexture(const char* filepath, int slot, BINDING_SHADER shader, const SAMPLER_DESC& samplerDesc, 
			TEXTURE_TYPE type=TEXTURE_TYPE_DEFAULT, ColorRamp& cr=ColorRamp());
		virtual ColorRamp& GetColorRamp(int slot, BINDING_SHADER shader);
		virtual void RefreshColorRampTexture(int slot, BINDING_SHADER shader);

		virtual void SetShaderFile(const char* shaderFile);
		virtual void SetCompileParameters(const char* cps);
		virtual void SetMaterialParameters(unsigned index, const Vec4& value);

		virtual const Vec4& GetAmbientColor() const;
		virtual const Vec4& GetDiffuseColor() const;
		virtual const Vec4& GetSpecularColor() const;
		virtual const Vec4& GetEmissiveColor() const;

		virtual const char* GetShaderFile() const;
		virtual void* GetShaderByteCode(unsigned& size) const;
		virtual const char* GetCompileParameters() const;
		virtual const Vec4& GetMaterialParameters(unsigned index) const;

		virtual void Bind();
		virtual void RegisterReloading();

	private:
		ITexture* CreateColorRampTexture(ColorRamp& cr);
		bool FindTextureIn(BINDING_SHADER shader, int slot, 
			// additional parameters. if match this function returns true.
			TEXTURE_TYPE type, const char* filepath, ITexture** pTextureInTheSlot) const;
		void RemoveTexture(ITexture* pTexture);

	protected:
		static std::vector<Material*> mMaterials;

		MATERIAL_CONSTANTS mMaterialConstants;
		SmartPtr<IShader> mShader;
		std::string mName;
		std::string mShaderFile;
		std::string mCompileParameters;
		typedef VectorMap<unsigned, Vec4> PARAMETER_VECTOR;
		PARAMETER_VECTOR mMaterialParameters;
		std::vector< SmartPtr<ITexture> > mTextures;
		bool mReloading;
		int mReloadingTryCount;
		typedef std::map<ITexture*, ColorRamp> COLOR_RAMP_MAP_TYPE;
		COLOR_RAMP_MAP_TYPE mColorRampMap;
	};
}